﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using TeamCommunitySolution.Domain.DataLayer.Venues;
using TeamCommunitySolution.Domain.DataLayer.Base;
using TeamCommunitySolution.Domain.DataLayer.Leagues;
using TeamCommunitySolution.Modules.Base.Responses;
using TeamCommunitySolution.Modules.Leagues;
using TeamCommunitySolution.Modules.Messaging;
using TeamCommunitySolution.Modules.Venues;
using TeamCommunitySolution.Repositories.Base;
using TeamCommunitySolution.Repositories.Leagues;
using TeamCommunitySolution.Repositories.Venues;
using TeamCommunitySolution.Modules.Base;
using TeamCommunitySolution.Modules.Venues.Requests;
using TeamCommunitySolution.Modules.Base.Requests;
using TeamCommunitySolution.Modules.Venues.Responses;
using TeamCommunitySolution.Modules.Shared;

namespace TeamCommunitySolution.Services.Services
{
    public class ApplicationService : IApplicationService
    {

        private static LeagueManager _leagueManager = LeagueManagerImpl.CreateInstance(LeagueRepositoryImpl.CreateInstance());
        private static MessageManager _messageManager = MessageManagerImpl.CreateInstance(BaseRepositoryImpl.CreateInstance());
        private static BaseManager _baseManager = BaseManagerImpl.CreateInstance(BaseRepositoryImpl.CreateInstance());
        private static VenueManager _venueManager = VenueManagerImpl.CreateInstance(VenueRepositoryImpl.CreateInstance());

        private ApplicationService()
        {
        }

        #region IApplicationService Members

        public void VenueCreate(Venue venue, string ownerId)
        {

            VenueRequest request = new VenueRequest();
            request.DateFounded = venue.DateFounded;
            request.Description = venue.Description;
            request.Latitude = venue.Latitude;
            request.Longditude = venue.Longditude;
            request.VenueName = venue.Name;
            request.Website = venue.Website;
            request.Owner = this.GetUserById(ownerId);
            VenueResponse response = _venueManager.CreateVenue(request);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error creating Venue at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }
        }

        public void VenueUpdate(Venue venue)
        {
            VenueRequest request = new VenueRequest();
            request.DateFounded = venue.DateFounded;
            request.Description = venue.Description;
            request.Id = venue.Id;
            request.Latitude = venue.Latitude;
            request.Longditude = venue.Longditude;
            request.VenueName = venue.Name;
            request.Owner = venue.Owner;

            VenueResponse response = _venueManager.UpdateVenue(request);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error updating Venue at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }
        }

        public void VenueRemove(string id)
        {
            VenueRequest request = new VenueRequest();
            request.Id = id;

            VenueResponse response = _venueManager.DeleteVenue(request);
            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error delete Venue at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }
        }

        public Venue VenueGetById(string id)
        {
            VenueRequest request = new VenueRequest();
            request.Id = id;

            VenueResponse response = _venueManager.GetVenueById(request);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error fetching Venue at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }

            return response.Venue;
        }

        public Team TeamGetById(string teamId)
        {
            TeamFetchRequest request = new TeamFetchRequest();
            request.Id = teamId;
            TeamResponse response = _baseManager.GetTeamById(request);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error get Team at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }

            return response.Team;
        }

        public void TeamSendMemberRequest(string teamId, string message, string userFromId, string userToId)
        {
            TeamFetchRequest teamRequest = new TeamFetchRequest();
            teamRequest.Id = teamId;

            TeamInviteRequest request = new TeamInviteRequest();
            request.PersonalMessage = message;
            request.Team = _baseManager.GetTeamById(teamRequest).Team;
            request.Owner = GetUserById(userFromId);
            request.UserFrom = request.Owner;
            request.UserTo = GetUserById(userToId);

            TeamInviteResponse response = _baseManager.SendTeamInvite(request);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error sending Team invite at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }
        }

        public void TeamHandleRequest(string teamRequestId, string username, bool isAccepted)
        {
            TeamMemberAddRequest addRequest = new TeamMemberAddRequest();
            addRequest.InviteId = teamRequestId;
            addRequest.IsAccepted = isAccepted;

            TeamResponse response = _baseManager.AddTeamMember(addRequest);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error adding team member at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }
        }

        /*
        public void TeamAddMemberTo(string teamId, string systemUserId)
        {
            _teamManager.AddMemberToTeam(teamId, systemUserId);
        }
         * */

        public void TeamCreate(string teamName, string description, DateTime dateFounded, string username)
        {
            TeamRequest request = new TeamRequest();
            request.DateFounded = dateFounded;
            request.Description = description;
            request.Name = teamName;
            request.Owner = this.GetUserByUsername(username);

            TeamResponse response = _baseManager.CreateTeam(request);

            if (response.Status == OperationStatus.Failure)
            {
                throw new Exception(String.Format("Error creating team at application service level. {0} {1}", response.Message, response.Exception.ToString()));
            }
        }

        /*
        public void TeamInviteMember(string teamId, string inviterId, string inviteeId, string personalMessage)
        {
            _teamManager.InviteTeamMember(teamId, inviterId, inviteeId, personalMessage);
        }
        **/

        public string[] TeamFindByName(string q)
        {
            return _teamManager.FindByName(q);
        }

        public Team TeamGetByName(string name)
        {
            return _teamManager.GetTeamByName(name);
        }

        public bool UserExists(string username, string password)
        {
            return _userManager.UserExists(username, password);
        }

        public MembershipUser UserCreate(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            return _userManager.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
        }

        public void UserCompleteRegistration(string email, string firstName, string lastName, string nickName, string genderId, string birthDate)
        {
            _userManager.CompleteRegistration(email, firstName, lastName, nickName, genderId, birthDate);
        }

        public bool UserEmailExists(string email)
        {
            return _userManager.EmailExists(email);
        }

        public SystemUser UserGetByUsername(string username)
        {
            return _userManager.GetUserByUsername(username);
        }

        public SystemUser UserGetById(string id)
        {
            return _userManager.GetUserById(id);
        }

        public SystemUser UserGetByNickname(string nickname)
        {
            return _userManager.GetUserByNickname(nickname);
        }

        public void UserSave(SystemUser user)
        {
            _userManager.SaveUser(user);
        }

        public void UserSaveList(List<SystemUser> userList)
        {
            _userManager.SaveUserList(userList);
        }

        public SystemUser UserGetByEmail(string email)
        {
            return _userManager.GetUserByEmail(email);
        }

        public string[] UserFindByName(string q)
        {
            return _userManager.FindByName(q);
        }

        public SystemUser UserFindByFormattedName(string formattedName)
        {
            return _userManager.FindByFormattedUserName(formattedName);
        }

        public void TeamAcceptRequest(string request, string id)
        {
            _userManager.AcceptRequest(request, id);
        }

        public void UserAddVenue(string name, string lat, string longd, string desc, string website, string ownerId, DateTime dateFounded)
        {
            _userManager.AddVenue(name, lat, longd, desc, website, ownerId, dateFounded);
        }

        public MessageInbox MessageGetReceivedForDisplay(string messageId, SystemUser user)
        {
            return _messageManager.GetReceivedMessageForDisplay(messageId, user);
        }

        public MessageOutbox MessageGetSentForDisplay(string messageId, SystemUser user)
        {
            return _messageManager.GetSentMessageForDisplay(messageId, user);
        }

        public void MessageDeleteInbox(string messageId)
        {
            _messageManager.DeleteInboxMessage(messageId);
        }

        public void MessageDeleteOutbox(string messageId)
        {
            _messageManager.DeleteOutboxMessage(messageId);
        }

        public void MessageSend(string userToId, string userFromId, string subject, string messageBody)
        {
            _messageManager.SendMessage(userToId, userFromId, subject, messageBody);
        }

        public void MessageSendTeam(string teamId, string p, string title, string messageContent)
        {
            _messageManager.SendTeamMessage(teamId, p, title, messageContent);
        }

        public void LeagueCreate(string name, string ownerId, int teamSize)
        {
            _leagueManager.CreateLeague(name, ownerId, teamSize);
        }

        public void LeagueUpdate(League league, SystemUser owner)
        {
            _leagueManager.UpdateLeague(league, owner);
        }

        public League LeagueGet(string id)
        {
            return _leagueManager.GetLeague(id);
        }

        public void LeagueInviteTeamTo(Team team, League league, string message, string host)
        {
            _leagueManager.InviteTeam(team, league, message, host);
        }

        public void LeagueAcceptInvite(SystemUser systemUser, string leagueId, string teamId)
        {
            _leagueManager.AcceptInvite(systemUser, leagueId, teamId);
        }

        public void LeagueCreateMeeting(string leagueId, LeagueMeeting leagueMeeting)
        {
            _leagueManager.CreateLeagueMeeting(leagueId, leagueMeeting);
        }

        #endregion

        public static IApplicationService CreateInstance()
        {
            return new ApplicationService();
        }

        private SystemUser GetUserById(string id)
        {
            SystemUserRequest request = new SystemUserRequest();
            request.Id = id;

            return _baseManager.GetSystemUserByUsername(request).SystemUser;
        }

        private SystemUser GetUserByUsername(string username)
        {
            SystemUserRequest request = new SystemUserRequest();
            request.Username = username;

            return _baseManager.GetSystemUserByUsername(request).SystemUser;
        }
    }
}
